package dao

import (
	"context"
	"fmt"
	"order_srv/basic/config"
	"order_srv/handler/models"
	"strconv"
	"time"
)

// AcceptOrder 接单操作
func AcceptOrder(ctx context.Context, orderID uint64, operatorType int32, operatorID int32, reason string) error {
	// 开始事务
	tx := config.DB.WithContext(ctx).Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 1. 检查订单状态
	var order models.Order
	err := tx.Where("id = ? AND order_status = ?", orderID, 0).First(&order).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("订单不存在或状态不正确: %v", err)
	}

	// 2. 检查操作员是否存在且可用
	var operator models.Operator
	err = tx.Where("operator_id = ? AND status = ?", strconv.Itoa(int(operatorID)), 1).First(&operator).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("操作员不存在或不可用: %v", err)
	}

	// 3. 检查操作员接单数量限制
	if operator.CurrentOrderCount >= operator.MaxOrderCount {
		tx.Rollback()
		return fmt.Errorf("操作员接单数量已达上限")
	}

	// 4. 更新订单状态
	if err := tx.Model(&order).Updates(map[string]interface{}{
		"order_status": 1, // 假设1是已确认
		"agent_id":     strconv.Itoa(int(operatorID)),
		"updated_at":   time.Now(),
	}).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("更新订单状态失败: %w", err)
	}

	// 5. 记录接单操作
	acceptance := models.OrderAcceptance{
		OrderID:      orderID,
		OrderNo:      order.OrderNo,
		OperatorID:   strconv.Itoa(int(operatorID)),
		OperatorType: strconv.Itoa(int(operatorType)),
		OperatorName: operator.OperatorName,
		Action:       "accept",
		Reason:       reason,
		ProcessedAt:  time.Now(),
		ResponseTime: time.Since(order.CreatedAt).Milliseconds(),
	}
	if err := tx.Create(&acceptance).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录接单操作失败: %w", err)
	}

	// 6. 更新操作员的接单统计
	operator.CurrentOrderCount++
	if err := tx.Save(&operator).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("更新操作员统计信息失败: %w", err)
	}

	// 7. 记录订单状态变更日志
	statusLog := models.OrderStatusLog{
		OrderID:      orderID,
		OrderNo:      order.OrderNo,
		OldStatus:    0, // 待确认
		NewStatus:    1, // 已确认
		OperatorID:   strconv.Itoa(int(operatorID)),
		OperatorType: int8(operatorType),
		Reason:       reason,
		CreatedAt:    time.Now(),
	}
	if err := tx.Create(&statusLog).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录订单状态日志失败: %w", err)
	}

	tx.Commit()
	return nil
}

// RejectOrder 拒绝订单操作
func RejectOrder(ctx context.Context, orderID uint64, operatorType int32, operatorID int32, reason string) error {
	// 开始事务
	tx := config.DB.WithContext(ctx).Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 1. 检查订单状态
	var order models.Order
	err := tx.Where("id = ? AND order_status = ?", orderID, 0).First(&order).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("订单不存在或状态不正确: %v", err)
	}

	// 2. 检查操作员是否存在且可用
	var operator models.Operator
	err = tx.Where("operator_id = ? AND status = ?", strconv.Itoa(int(operatorID)), 1).First(&operator).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("操作员不存在或不可用: %v", err)
	}

	// 3. 更新订单状态为拒绝
	if err := tx.Model(&order).Updates(map[string]interface{}{
		"order_status": 2, // 假设2是已拒绝
		"updated_at":   time.Now(),
	}).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("更新订单状态失败: %w", err)
	}

	// 4. 记录拒绝操作
	acceptance := models.OrderAcceptance{
		OrderID:      orderID,
		OrderNo:      order.OrderNo,
		OperatorID:   strconv.Itoa(int(operatorID)),
		OperatorType: strconv.Itoa(int(operatorType)),
		OperatorName: operator.OperatorName,
		Action:       "reject",
		Reason:       reason,
		ProcessedAt:  time.Now(),
		ResponseTime: time.Since(order.CreatedAt).Milliseconds(),
	}
	if err := tx.Create(&acceptance).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录拒绝操作失败: %w", err)
	}

	// 5. 记录订单状态变更日志
	statusLog := models.OrderStatusLog{
		OrderID:      orderID,
		OrderNo:      order.OrderNo,
		OldStatus:    0, // 待确认
		NewStatus:    2, // 已拒绝
		OperatorID:   strconv.Itoa(int(operatorID)),
		OperatorType: int8(operatorType),
		Reason:       reason,
		CreatedAt:    time.Now(),
	}
	if err := tx.Create(&statusLog).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录订单状态日志失败: %w", err)
	}

	tx.Commit()
	return nil
}

// AssignOrder 分配订单操作
func AssignOrder(ctx context.Context, orderID uint64, assignedTo string, assignedBy string, assignmentNote string) error {
	//开始事务
	tx := config.DB.WithContext(ctx).Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	//1.检查订单状态
	var order models.Order
	err := tx.Where("id = ? AND order_status = ?", orderID, 0).First(&order).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("订单不存在或状态不正确：%v", err)
	}

	//2.检查被分配操作员是否存在且可用
	var operator models.Operator
	err = tx.Where("operator_id = ? AND status = ?", assignedTo, 1).First(&operator).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("被分配操作员不存在或不可用：%v", err)
	}

	//3.更新订单状态和分配信息
	if err = tx.Model(&order).Updates(map[string]interface{}{
		"order_status": 3,
		"agent_id":     assignedTo,
		"updated_at":   time.Now(),
	}).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("更新订单状态失败：%w", err)
	}

	// 4. 记录分配操作
	acceptance := models.OrderAcceptance{
		OrderID:      orderID,
		OrderNo:      order.OrderNo,
		OperatorID:   assignedTo,
		OperatorType: strconv.Itoa(int(operator.OperatorType)),
		OperatorName: operator.OperatorName,
		Action:       "assign",
		Reason:       assignmentNote,
		ProcessedAt:  time.Now(),
		ResponseTime: time.Since(order.CreatedAt).Milliseconds(),
	}
	if err := tx.Create(&acceptance).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录分配操作失败: %w", err)
	}

	// 5. 记录订单状态变更日志
	statusLog := models.OrderStatusLog{
		OrderID:      orderID,
		OrderNo:      order.OrderNo,
		OldStatus:    0, // 待确认
		NewStatus:    3, // 已分配
		OperatorID:   assignedBy,
		OperatorType: 3, // 假设3是管理员
		Reason:       assignmentNote,
		CreatedAt:    time.Now(),
	}
	if err := tx.Create(&statusLog).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录订单状态日志失败: %w", err)
	}

	tx.Commit()
	return nil
}

// GetPendingOrders 获取待处理订单
func GetPendingOrders(ctx context.Context, page int32, pageSize int32, status int32, operatorID int32) ([]models.Order, int64, error) {
	var orders []models.Order
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.Order{})

	// 根据状态筛选
	if status > 0 {
		query = query.Where("order_status = ?", status)
	}

	// 根据操作员ID筛选（如果提供）
	if operatorID > 0 {
		query = query.Where("agent_id = ?", strconv.Itoa(int(operatorID)))
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取订单总数失败: %w", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(int(offset)).Limit(int(pageSize)).Order("created_at DESC").Find(&orders).Error; err != nil {
		return nil, 0, fmt.Errorf("获取订单列表失败: %w", err)
	}

	return orders, total, nil
}

// GetOrderAcceptanceStats 获取接单统计
func GetOrderAcceptanceStats(ctx context.Context, operatorID string, startDate string, endDate string) (map[string]interface{}, error) {
	var stats map[string]interface{} = make(map[string]interface{})

	// 构建查询条件
	query := config.DB.WithContext(ctx).Model(&models.OrderAcceptance{})

	if operatorID != "" {
		query = query.Where("operator_id = ?", operatorID)
	}

	if startDate != "" {
		query = query.Where("created_at >= ?", startDate)
	}

	if endDate != "" {
		query = query.Where("created_at <= ?", endDate)
	}

	// 总接单数
	var totalAccept int64
	if err := query.Where("action = ?", "accept").Count(&totalAccept).Error; err != nil {
		return nil, fmt.Errorf("获取接单总数失败: %w", err)
	}

	// 总拒绝数
	var totalReject int64
	if err := query.Where("action = ?", "reject").Count(&totalReject).Error; err != nil {
		return nil, fmt.Errorf("获取拒绝总数失败: %w", err)
	}

	// 平均响应时间
	var avgResponseTime float64
	if err := query.Select("AVG(response_time)").Where("action = ?", "accept").Scan(&avgResponseTime).Error; err != nil {
		return nil, fmt.Errorf("获取平均响应时间失败: %w", err)
	}

	// 接单率
	var acceptanceRate float64
	if totalAccept+totalReject > 0 {
		acceptanceRate = float64(totalAccept) / float64(totalAccept+totalReject) * 100
	}

	stats["total_accept"] = totalAccept
	stats["total_reject"] = totalReject
	stats["acceptance_rate"] = acceptanceRate
	stats["avg_response_time"] = avgResponseTime

	return stats, nil
}

// BatchAcceptOrders 批量接单
func BatchAcceptOrders(ctx context.Context, orderIDs []uint64, operatorID int32, operatorType int32, reason string) (int32, int32, []string, error) {
	var successCount int32
	var failedCount int32
	var failedOrders []string

	for _, orderID := range orderIDs {
		err := AcceptOrder(ctx, orderID, operatorType, operatorID, reason)
		if err != nil {
			failedCount++
			failedOrders = append(failedOrders, fmt.Sprintf("订单%d: %v", orderID, err))
		} else {
			successCount++
		}
	}

	return successCount, failedCount, failedOrders, nil
}

// BatchRejectOrders 批量拒绝订单
func BatchRejectOrders(ctx context.Context, orderIDs []uint64, operatorID int32, operatorType int32, reason string) (int32, int32, []string, error) {
	var successCount int32
	var failedCount int32
	var failedOrders []string

	for _, orderID := range orderIDs {
		err := RejectOrder(ctx, orderID, operatorType, operatorID, reason)
		if err != nil {
			failedCount++
			failedOrders = append(failedOrders, fmt.Sprintf("订单%d: %v", orderID, err))
		} else {
			successCount++
		}
	}

	return successCount, failedCount, failedOrders, nil
}

// GetOrdersByStatus 按状态获取订单
func GetOrdersByStatus(ctx context.Context, status int32, page int32, pageSize int32) ([]models.Order, int64, error) {
	var orders []models.Order
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.Order{}).Where("order_status = ?", status)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取订单总数失败: %w", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(int(offset)).Limit(int(pageSize)).Order("created_at DESC").Find(&orders).Error; err != nil {
		return nil, 0, fmt.Errorf("获取订单列表失败: %w", err)
	}

	return orders, total, nil
}

